from dataclasses import dataclass
from collections import OrderedDict
import pickle
from tqdm import tqdm
import matplotlib.pyplot as plt

CACHE_SIZE: int

@dataclass
class Recipe:
    name: str
    cons: list

@dataclass
class TempRecipe:
    
    name: str
    cons: list

class LRUCache:
    def __init__(self, capacity: int):
        self.cache = OrderedDict()  # 存储键值对
        self.capacity = capacity  # 缓存容量

    def get(self, key):
        if key not in self.cache:
            return None
        else:
            # 将访问过的key移动到末尾
            self.cache.move_to_end(key)
            return self.cache[key]

    def put(self, key, value) -> None:
        if key in self.cache:
            # 如果key已经存在，则更新其值并移动到末尾
            self.cache.move_to_end(key)
        self.cache[key] = value
        if len(self.cache) > self.capacity:
            # 超过容量，删除最先添加的元素
            self.cache.popitem(last=False)

def dumpRecipe():
    recipeList = []
    with open("recipes", "r") as f:
        for line in f:
            content = line.strip().strip(',').split(',')
            name = content[0]
            num = int(content[1])
            cons = list(map(int, content[2:]))
            assert len(cons) == num
            name = name.strip('/')

            recipeList.append(Recipe(name, cons))

            print(f"{name}: {len(cons)} {len(set(cons))}")
    
    with open("recipeList", "wb") as f:
        pickle.dump(recipeList, f)

def simulateDestor(recipeList):
    INDEX_LOOKUP = 0
    INDEX_HIT = 0
    REPROCESS = 0
    READ_CONTAINER = 0
    print(f"CACHE_SIZE: {CACHE_SIZE} {CACHE_SIZE * 4 / 1024:.2f}GB")
    cache = LRUCache(CACHE_SIZE)
    processed = []

    for recipe in tqdm(recipeList):
        for con in recipe.cons:
            INDEX_LOOKUP += 1
            if cache.get(con) is not None:
                INDEX_HIT += 1
                continue

            if con in processed:
                REPROCESS += 1
            else:
                READ_CONTAINER += 1
                processed.append(con)
            cache.put(con, 1)
    
    print(f"INDEX_LOOKUP: {INDEX_LOOKUP}")
    print(f"READ_CONTAINER: {READ_CONTAINER}")
    print(f"INDEX_HIT: {INDEX_HIT}")
    print(f"REPROCESS: {REPROCESS}")

def main():
    with open("recipeList", "rb") as f:
        recipeList = pickle.load(f)
    
    print('2D')
    simulateDestor(recipeList)

    # reOrder recipeList
    d = {'l': 1, '2': 2, 'r': 3}
    recipeList.sort(key=lambda x: d[x.name[0]], reverse=False)

    print('Similarity')
    simulateDestor(recipeList)
    
if __name__ == '__main__':
    CACHE_SIZE = int(256 * 10)  # 3 10
    main()